/* 
 * File:   Lista.cpp
 * Author: mauro
 * 
 * Created on 11 de septiembre de 2014, 01:13
 */
#include "Lista.h"


// Crea una lista.
// Post: devuelve una nueva lista vacía.

template<class Tipo>
Lista<Tipo>::Lista() {
    primero = NULL;
    ultimo = NULL;
    cantidad = 0;
    //cout << "CONSTRUCTOR DE LISTA" << endl;
}



//creo una lista con datos!
template<class Tipo>
Lista<Tipo>::Lista(Tipo dato) {

    Nodo<Tipo> *nodoNuevo = new Nodo<Tipo>(dato);

    this->primero = nodoNuevo;
    this->ultimo = nodoNuevo;
    this->cantidad = 1;
}
template<class Tipo>
void Lista<Tipo>::eliminarNodo(Nodo<Tipo> *nodo) {
    delete nodo;
}


// Devuelve verdadero o falso, según si la lista tiene o no elementos enlazados.
// Pre: la lista fue creada.
template<class Tipo>
bool Lista<Tipo>::estaVacia() {
    return (this->cantidad == 0);
}

// Destruye la lista. Si se recibe la función destruir_dato por parámetro,
// para cada uno de los elementos de la lista llama a destruir_dato.
// Pre: la lista fue creada. 'destruir_dato' es una función capaz de destruir
// los datos de la cola, o NULL en caso de que no se la utilice.
// Post: se eliminaron todos los elementos de la lista.
template<class Tipo>
Lista<Tipo>::~Lista() {
    while (!this->estaVacia()) {
        Nodo<Tipo> *aux = this->getPrimero();
        this->primero = aux->getSiguiente();
        this->eliminarNodo(aux);
        this->cantidad--;
    }
}


// Agrega un nuevo elemento a la lista. Devuelve falso en caso de error.
// Pre: la lista fue creada.
// Post: se agregó un nuevo elemento al principio o al final de la lista
// según corresponda, 'dato' es dicho elemento.
template<class Tipo>
bool Lista<Tipo>::insertarPrimero(Tipo dato) {

    Nodo<Tipo> *nodoNuevo = new Nodo<Tipo>(dato);

    if (this->estaVacia()) {
        this->primero = nodoNuevo;
        this->ultimo = nodoNuevo;
        this->cantidad++;
        return true;
    }
    nodoNuevo->setSiguiente(this->primero);
    this->primero = nodoNuevo;
    this->cantidad++;

    return true;
}

/*********************************************************************/
template<class Tipo>
bool Lista<Tipo>::insertarUltimo(Tipo dato) {

    Nodo<Tipo> *nodoNuevo = new Nodo<Tipo>(dato);

    if (this->estaVacia()) {
        this->primero = nodoNuevo;
        this->ultimo = nodoNuevo;
        this->cantidad++;
        return true;
    }
    this->ultimo->setSiguiente(nodoNuevo);
    this->ultimo = nodoNuevo;
    this->cantidad++;
    return true;
}

// Obtiene el valor del primer elemento de la lista. Si la lista tiene elementos,
// se devuelve el valor del primer elemento. Si está vacía devuelve NULL.
// Pre: la lista fue creada.
// Post: se devolvió el valor del primer elemento de la lista sin sacarlo
// de ella, cuando ésta no está vacía; NULL en caso contrario.
//template<typename T>
template<class Tipo>
Tipo Lista<Tipo>::verPrimero() {
    if (this->estaVacia())
        return NULL;
    return this->primero->getDato();
}
template<class Tipo>
Tipo Lista<Tipo>::verUltimo() {
    if (this->estaVacia())
        return NULL;
    return this->ultimo->getDato();
}

// Saca el primer elemento de la lista. Si la lista tiene elementos,
// se quita el primero de la lista, y se devuelve ese valor. Si la lista
// está vacía, devuelve NULL.
// Pre: la lista fue creada.
// Post: si la lista no estaba vacía, se devuelve el primer valor de ella
// y la lista contiene un elemento menos.
template<class Tipo>
Tipo Lista<Tipo>::borrarPrimero() {
    if (this->estaVacia())
        return NULL;
    Nodo<Tipo> *nodoAux = this->primero;
    Tipo dato = nodoAux->getDato();

    this->primero = this->primero->getSiguiente();
    this->cantidad--;

    this->eliminarNodo(nodoAux);
    return dato;
}

// Devuelve el largo de la lista.
// Pre: la lista fue creada.
// Post: se devolvió el largo de la lista. En caso de estar vacía,
// lógicamente, la función devuelve 0 (cero).
template<class Tipo>
int Lista<Tipo>::getLargo() {
    return this->cantidad;
}

//Se obtiene el Primer elemento de la lista.
template<class Tipo>
Nodo<Tipo>* Lista<Tipo>::getPrimero() {
    return this->primero;
}
//Se obtiene el Ultimo elemento de la lista.
template<class Tipo>
Nodo<Tipo>* Lista<Tipo>::getUltimo() {
    return this->ultimo;
}